KokaのEffect Types
関数の型を3箇所で表す
(引数) -> <EffectTypes> 返り値
例
このシグネチャのtotalとかexnの部分がEffect Types
code:koka(js)
fun sqr : (int) -> total int
fun divide : (int,int) -> exn int
fun turing : (tape) -> div int
fun print : (string) -> console ()
fun rand : () -> ndet int
これらはいずれも推論の対象になる
docs上ではhoverすると推論された結果を見れる
https://gyazo.com/56cdcdebb2fc101a91100230945e8a89
個々のEffect Typesを組み合わせることもできる
code:koka(js)
alias pure = <div,exn>
当然、複数のEffect Typesを持つ関数も定義できる
code:koka(js)
fun looptest()
while { is-odd(srandom-int()) }
throw("odd")
table:個々の関数の返り値
while <div|e> types/()
is-odd total bool
scrandom-int ndet int
throw exn a
従って、このlooptest()の返り値は、<pure,ndet> ()と推論される
Effect Typesはbuilt-inで用意されているものも多く、また自分で定義することもできる
total, <>
全域関数である
Effectが存在しないことを表す
単位元的な
exn
例外が発生する可能性がある
部分関数である
divergent
関数が終了しない可能性がある
consoleに書き込む可能性がある
非決定的
純粋関数である
exnとdivの組み合わせのことをpureと呼ぶのちょっとビビるが、まあ実際そうか
The combination of exn and div is called pure as that corresponds to Haskell's notion of purity. ref st<h> = <read<h>,write<h>,alloc<h>>
mutablityは、read/write/allocの組み合わせ
effect typesもpolymorphicなんですなmrsekut.icon
io = <exn,div,ndet,console,net,fsys,ui,st<global>> ref 全部盛りじゃんmrsekut.icon
etc.
Effect Typesの定義
code:koka(js)
effect raise // ①
ctl raise( msg : string ) : a // ②
effectとctlがキーワード
①でraiseという名前のeffect typesを定義してる
②でそのoperationとしてraise( msg : string ) : aを定義
これらは異なる名前でも良い
typeとoperationが同じ場合は以下のように省略しても書ける
code:koka(js)
effect ctl raise(msg: string): a
Polymorphic Effects
例: map : (xs : list<a>, f : (a) -> e b) -> e list<b>
mapの返り値のEffect typesは、引数fのEffect typesを引き継ぐ
< .. | e>のように書いて、effectsを追加できることを示せる
例: while : ( pred : () -> <div|e> bool, action : () -> <div|e> () ) -> <div|e> ()
気持ち的には上のmapと同じだが、
while : ( pred : () -> e bool, action : () -> e () ) -> e ()
whileは無限ループの可能性があるので、diveffectを追加する
なので、<div|e>のようにpolymorphicでありつつも、effectsを拡張した型になる
内部の書き方を変えることでeffect typeが変わる例 ref 再帰するとdivが必要になる
code:koka(js)
fun fib(n : int) : div int
if n <= 0 then 0
elif n == 1 then 1
else fib(n - 1) + fib(n - 2)
これをmutable変数を使うことで、totalに変えられる
code:koka(js)
fun fib2(n)
var x := 0
var y := 1
repeat(n)
val y0 = y
y := x+y
x := y0
x
types/()って型はなに?
普通にユニット型()のことかなmrsekut.icon
types/はmodule名でしょう
^nという表記は何?
型クラス的なものはないのか
ad hoc多相がない(?)から、同じ関数を型ごとにoverloadしまくってる
例えばshowするときにどうする?